package com.pine.dbant.core.config;

import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 请求参数时间格式自动转换器。
 * 全局统一处理：对前台请求参数传入的时间字符串，RequestParam为Date类型时，接收时自动转换
 * 支持多种时间日期格式以及时间戳格式
 * 支持REST接口入参传Date型，例如 url= xxxx?startTime=1606793635990, 后台可以用Date对象接受startTime
 *
 * @author huangli
 * @date 2020.12.14
 */
public class DateConverter implements Converter<String, Date> {

    /**
     * 支持的时间格式
     */
    private static final String[] FORMATS = new String[]{
            "yyyy-MM",
            "yyyy-MM-dd",
            "yyyy-MM-dd HH:mm",
            "yyyy-MM-dd HH:mm:ss",
            "yyyy-MM-dd'T'HH:mm",
            "yyyy-MM-dd'T'HH:mm:ss",
            "yyyy/MM",
            "yyyy/MM/dd",
            "yyyy/MM/dd HH:mm",
            "yyyy/MM/dd HH:mm:ss",
            "yyyy/MM/dd'T'HH:mm",
            "yyyy/MM/dd'T'HH:mm:ss"
    };

    /**
     * 支持的时间格式化器
     */
    private static final DateFormat[] DATE_FORMATS;

    static {
        DATE_FORMATS = new DateFormat[FORMATS.length];
        for (int i = 0; i < FORMATS.length; i++) {
            DATE_FORMATS[i] = new SimpleDateFormat(FORMATS[i]);
        }
    }

    @Override
    public Date convert(String source) {
        String value = source.trim();
        if ("".equals(value)) {
            return null;
        }
        if (source.matches("^\\d{4}-\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[0]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[1]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[2]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[3]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[4]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[5]);
        } else if (source.matches("^\\d{4}/\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[6]);
        } else if (source.matches("^\\d{4}/\\d{1,2}/\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[7]);
        } else if (source.matches("^\\d{4}/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[8]);
        } else if (source.matches("^\\d{4}/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[9]);
        } else if (source.matches("^\\d{4}/\\d{1,2}/\\d{1,2}T\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[10]);
        } else if (source.matches("^\\d{4}/\\d{1,2}/\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, DATE_FORMATS[11]);
        } else if (source.matches("^\\d+$")) {
            // 时间戳格式 1606793635000 epochMilliSeconds
            return new Date(Long.parseLong(source));
        } else {
            // 其他格式
            return new Date(source);
//            throw new IllegalArgumentException("Invalid date value '" + source + "'");
        }
    }

    /**
     * 格式化日期
     *
     * @param dateStr    字符型日期
     * @param dateFormat 格式
     * @return Date 日期
     */
    private static Date parseDate(String dateStr, DateFormat dateFormat) {
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (Exception e) {
            // do nothing
        }
        return date;
    }
}